<template>
  <div class="container">
    <h1>李佳豪的文件上传系统</h1>
    <h1>StuId：2251221137</h1>
    
    <div class="upload-area" @dragover.prevent @drop.prevent="handleDrop">
      <div v-if="!selectedFile">
        <p>将文件拖拽到此处或</p>
        <input type="file" ref="fileInput" @change="handleFileSelect" style="display: none;" />
        <button @click="triggerFileSelect" class="btn-upload">选择文件</button>
      </div>
      <div v-else class="file-info">
        <p>{{ selectedFile.name }}</p>
        <p>{{ formatFileSize(selectedFile.size) }}</p>
        <button @click="triggerFileSelect" class="btn-upload">更换文件</button>
      </div>
    </div>
    
    <button @click="uploadFile" :disabled="!selectedFile || uploading" class="btn-primary">
      {{ uploading ? '上传中...' : '上传文件' }}
    </button>
    
    <div v-if="uploading" class="progress-container">
      <div class="progress-bar">
        <div class="progress-fill" :style="{ width: uploadProgress + '%' }"></div>
      </div>
      <p>进度: {{ uploadProgress }}%</p>
    </div>
    
    <div v-if="message" :class="['message', messageType]">
      {{ message }}
    </div>
    
    <!-- 文件列表区域 -->
    <div class="file-list-section">
      <div class="file-list-header">
        <h2>已上传文件</h2>
        <button @click="fetchFiles" class="btn-refresh">刷新列表</button>
      </div>
      
      <div v-if="loadingFiles" class="loading">
        加载中...
      </div>
      
      <div v-else-if="files.length === 0" class="empty-state">
        暂无上传的文件
      </div>
      
      <table v-else class="file-table">
        <thead>
          <tr>
            <th>文件名</th>
            <th>大小</th>
            <th>上传时间</th>
            <th>操作</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="file in files" :key="file.id">
            <td>{{ file.fileName }}</td>
            <td>{{ formatFileSize(file.fileSize) }}</td>
            <td>{{ formatDate(file.uploadTime) }}</td>
            <td>
              <button @click="downloadFile(file.id, file.fileName)" class="btn-action btn-download">下载</button>
              <button @click="confirmDelete(file.id, file.fileName)" class="btn-action btn-delete">删除</button>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
    
    <!-- 删除确认对话框 -->
    <div v-if="showDeleteModal" class="modal-overlay">
      <div class="modal">
        <h3>确认删除</h3>
        <p>确定要删除文件 "{{ fileToDeleteName }}" 吗？</p>
        <div class="modal-actions">
          <button @click="deleteFile" class="btn-primary btn-danger">确认删除</button>
          <button @click="cancelDelete" class="btn-secondary">取消</button>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      selectedFile: null,
      uploading: false,
      uploadProgress: 0,
      message: '',
      messageType: '',
      files: [],
      loadingFiles: false,
      showDeleteModal: false,
      fileToDeleteId: '',
      fileToDeleteName: ''
    }
  },
  mounted() {
    // 组件挂载后自动加载文件列表
    this.fetchFiles()
  },
  methods: {
    triggerFileSelect() {
      this.$refs.fileInput.click()
    },
    handleFileSelect(event) {
      if (event.target.files.length > 0) {
        this.selectedFile = event.target.files[0]
        this.message = ''
      }
    },
    handleDrop(event) {
      if (event.dataTransfer.files.length > 0) {
        this.selectedFile = event.dataTransfer.files[0]
        this.message = ''
      }
    },
    formatFileSize(bytes) {
      if (bytes === 0) return '0 B'
      const k = 1024
      const sizes = ['B', 'KB', 'MB', 'GB']
      const i = Math.floor(Math.log(bytes) / Math.log(k))
      return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
    },
    formatDate(dateString) {
      if (!dateString) return ''
      const date = new Date(dateString)
      if (isNaN(date.getTime())) return dateString
      
      const year = date.getFullYear()
      const month = String(date.getMonth() + 1).padStart(2, '0')
      const day = String(date.getDate()).padStart(2, '0')
      const hours = String(date.getHours()).padStart(2, '0')
      const minutes = String(date.getMinutes()).padStart(2, '0')
      
      return `${year}-${month}-${day} ${hours}:${minutes}`
    },
    uploadFile() {
      if (!this.selectedFile) return
      
      const formData = new FormData()
      formData.append('file', this.selectedFile)
      
      this.uploading = true
      this.uploadProgress = 0
      
      const xhr = new XMLHttpRequest()
      
      xhr.upload.addEventListener('progress', (event) => {
        if (event.lengthComputable) {
          this.uploadProgress = Math.round((event.loaded / event.total) * 100)
        }
      })
      
      xhr.addEventListener('load', () => {
        this.uploading = false
        if (xhr.status === 200) {
          this.message = '文件上传成功！'
          this.messageType = 'success'
          console.log('响应:', xhr.responseText)
          // 重置文件选择
          this.selectedFile = null
          // 安全地重置文件输入框
          if (this.$refs.fileInput) {
            this.$refs.fileInput.value = ''
          }
          // 上传成功后刷新文件列表
          this.fetchFiles()
        } else {
          this.message = '上传失败，请重试'
          this.messageType = 'error'
        }
      })
      
      xhr.addEventListener('error', () => {
        this.uploading = false
        this.message = '网络错误，请检查连接'
        this.messageType = 'error'
      })
      
      xhr.open('POST', '/api/upload')
      xhr.send(formData)
    },
    // 获取文件列表
    fetchFiles() {
      this.loadingFiles = true
      
      fetch('/api/files')
        .then(response => {
          if (!response.ok) {
            throw new Error('获取文件列表失败')
          }
          return response.json()
        })
        .then(data => {
          this.files = data || []
          this.loadingFiles = false
        })
        .catch(error => {
          console.error('获取文件列表错误:', error)
          this.message = '获取文件列表失败'
          this.messageType = 'error'
          this.loadingFiles = false
        })
    },
    // 下载文件
    downloadFile(fileId, fileName) {
      const xhr = new XMLHttpRequest()
      xhr.open('GET', `/api/files/${fileId}`, true)
      xhr.responseType = 'blob'
      
      xhr.onload = () => {
        if (xhr.status === 200) {
          // 创建下载链接
          const url = window.URL.createObjectURL(new Blob([xhr.response]))
          const link = document.createElement('a')
          link.href = url
          link.setAttribute('download', fileName)
          document.body.appendChild(link)
          link.click()
          
          // 清理
          document.body.removeChild(link)
          window.URL.revokeObjectURL(url)
        } else {
          this.message = '文件下载失败'
          this.messageType = 'error'
        }
      }
      
      xhr.onerror = () => {
        this.message = '网络错误，文件下载失败'
        this.messageType = 'error'
      }
      
      xhr.send()
    },
    // 确认删除
    confirmDelete(fileId, fileName) {
      this.fileToDeleteId = fileId
      this.fileToDeleteName = fileName
      this.showDeleteModal = true
    },
    // 取消删除
    cancelDelete() {
      this.showDeleteModal = false
      this.fileToDeleteId = ''
      this.fileToDeleteName = ''
    },
    // 删除文件
    deleteFile() {
      fetch(`/api/files/${this.fileToDeleteId}`, {
        method: 'DELETE',
        headers: {
          'Content-Type': 'application/json'
        }
      })
      .then(response => {
        if (!response.ok) {
          throw new Error('删除文件失败')
        }
        return response.json()
      })
      .then(data => {
        this.message = '文件删除成功'
        this.messageType = 'success'
        // 刷新文件列表
        this.fetchFiles()
      })
      .catch(error => {
        console.error('删除文件错误:', error)
        this.message = '文件删除失败'
        this.messageType = 'error'
      })
      .finally(() => {
        this.showDeleteModal = false
        this.fileToDeleteId = ''
        this.fileToDeleteName = ''
      })
    }
  }
}
</script>

<style>
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
  background-color: #f5f5f5;
  color: #333;
}

.container {
  max-width: 800px;
  margin: 50px auto;
  padding: 20px;
  background-color: white;
  border-radius: 8px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}

h1 {
  text-align: center;
  margin-bottom: 30px;
  color: #2c3e50;
}

h2 {
  color: #34495e;
  margin-bottom: 20px;
}

.upload-area {
  border: 2px dashed #3498db;
  border-radius: 8px;
  padding: 40px 20px;
  text-align: center;
  margin-bottom: 20px;
  transition: border-color 0.3s;
}

.upload-area:hover {
  border-color: #2980b9;
}

.file-info {
  text-align: center;
}

.file-info p:first-child {
  font-weight: bold;
  margin-bottom: 5px;
}

.file-info p:last-child {
  color: #7f8c8d;
  margin-bottom: 15px;
  font-size: 0.9em;
}

.btn-upload,
.btn-primary,
.btn-secondary,
.btn-refresh,
.btn-action {
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 16px;
  transition: background-color 0.3s;
}

.btn-upload {
  background-color: #3498db;
  color: white;
}

.btn-upload:hover {
  background-color: #2980b9;
}

.btn-primary {
  background-color: #27ae60;
  color: white;
  width: 100%;
  margin-bottom: 20px;
}

.btn-primary:hover:not(:disabled) {
  background-color: #229954;
}

.btn-primary:disabled {
  background-color: #95a5a6;
  cursor: not-allowed;
}

.btn-secondary {
  background-color: #95a5a6;
  color: white;
}

.btn-secondary:hover {
  background-color: #7f8c8d;
}

.btn-refresh {
  background-color: #f39c12;
  color: white;
  padding: 8px 16px;
  font-size: 14px;
}

.btn-refresh:hover {
  background-color: #e67e22;
}

.btn-action {
  padding: 6px 12px;
  font-size: 14px;
  margin-right: 8px;
}

.btn-download {
  background-color: #3498db;
  color: white;
}

.btn-download:hover {
  background-color: #2980b9;
}

.btn-delete {
  background-color: #e74c3c;
  color: white;
}

.btn-delete:hover {
  background-color: #c0392b;
}

.btn-danger {
  background-color: #e74c3c;
}

.btn-danger:hover {
  background-color: #c0392b;
}

.progress-container {
  margin-bottom: 20px;
}

.progress-bar {
  width: 100%;
  height: 20px;
  background-color: #ecf0f1;
  border-radius: 10px;
  overflow: hidden;
  margin-bottom: 10px;
}

.progress-fill {
  height: 100%;
  background-color: #27ae60;
  transition: width 0.3s ease;
}

.message {
  padding: 15px;
  border-radius: 4px;
  font-weight: bold;
  margin-bottom: 20px;
}

.message.success {
  background-color: #d4edda;
  color: #155724;
  border: 1px solid #c3e6cb;
}

.message.error {
  background-color: #f8d7da;
  color: #721c24;
  border: 1px solid #f5c6cb;
}

/* 文件列表样式 */
.file-list-section {
  margin-top: 40px;
}

.file-list-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

.file-table {
  width: 100%;
  border-collapse: collapse;
}

.file-table th,
.file-table td {
  padding: 12px;
  text-align: left;
  border-bottom: 1px solid #ddd;
}

.file-table th {
  background-color: #f8f9fa;
  font-weight: bold;
  color: #34495e;
}

.file-table tr:hover {
  background-color: #f8f9fa;
}

.loading {
  text-align: center;
  padding: 20px;
  color: #7f8c8d;
  font-style: italic;
}

.empty-state {
  text-align: center;
  padding: 40px;
  color: #7f8c8d;
  font-style: italic;
  background-color: #f8f9fa;
  border-radius: 8px;
}

/* 模态框样式 */
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.modal {
  background-color: white;
  padding: 30px;
  border-radius: 8px;
  width: 90%;
  max-width: 400px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
}

.modal h3 {
  margin-bottom: 15px;
  color: #2c3e50;
}

.modal p {
  margin-bottom: 20px;
  color: #34495e;
}

.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

/* 响应式样式 */
@media (max-width: 600px) {
  .container {
    margin: 20px;
    padding: 15px;
  }
  
  .file-list-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
  }
  
  .file-table {
    font-size: 14px;
  }
  
  .file-table th,
  .file-table td {
    padding: 8px;
  }
  
  .btn-action {
    padding: 4px 8px;
    font-size: 12px;
    margin-right: 4px;
  }
  
  .modal {
    padding: 20px;
  }
}
</style>